package com.yorick.netty;

import com.yorick.netty.utils.SysConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class WebSocketServer {
    private final static int port = Integer.parseInt(SysConfig.getInstance().getProperty("websocket_port"));
    /**
     * boss 线程组，用于服务端接受客户端的连接
     */
    private EventLoopGroup bossGroup = new NioEventLoopGroup();
    /**
     * worker 线程组，用于服务端接受客户端的数据读写
     */
    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    /**
     * /**
     * Netty Server Channel
     */
    private Channel channel;

    public void start() {

        // 1.创建对应的EventLoopGroup对象
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        // websocket 相关的配置
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        //因为基于http协议，使用http的编码和解码器
                        pipeline.addLast(new HttpServerCodec());
                        //是以块方式写，添加ChunkedWriteHandler处理器
                        pipeline.addLast(new ChunkedWriteHandler());
                        pipeline.addLast(new HttpObjectAggregator(8192));
                        pipeline.addLast(new WebSocketServerProtocolHandler("/"));
                        // 自定义handler，处理业务逻辑
                        pipeline.addLast(new WebSocketServerHandler());

                    }
                });
        try {
            ChannelFuture f = bootstrap.bind(port).sync();
            channel = f.channel();
            log.info("Netty WebSocket服务器已启动: {}", channel.localAddress());
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public void stop() {
        log.info("Netty WebSocket服务器已关闭");
        // 优雅的关闭EventLoopGroup，释放所有的资源
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
